#include <iostream>
#include <string>

#include "user.pb.h"
#include "mprpcapplication.h"
#include "rpcprovider.h"

/**
 * UserService 原先是一个本地服务，提供了两个进程内的本地方法
 * Login GetFriendList

class UserService
{
public:
    bool Login(std::string name, std::string pwd)
    {
        std::cout << "doing local service: Login " << std::endl;
        std::cout << "name: " << name << " --- pwd: " << pwd << std::endl;

        return true;
    }
};
*/

/**
 * 改成 rpc 服务，使用在 RPC 发布端（提供者）
*/
class UserService : public fixbug::UserServiceRpc  // 找不到方法是没加名字空间
{
public:
    bool Login(std::string name, std::string pwd)
    {
        std::cout << "doing local service: Login " << std::endl;
        std::cout << "name: " << name << " --- pwd: " << pwd << std::endl;

        return true;
    }

    bool Register(uint32_t id, std::string name, std::string pwd)
    {
        std::cout << "doing register service: Login " << std::endl;
        std::cout << "id: " << id << " --- name: " << name << " --- pwd: " << pwd << std::endl;
        return true;
    }

    // 下面这些方法都是框架直接调用的
    /**
     * 重写基类UserServiceRpc的虚函数
     * 1. Caller ==> Login(LoginRequest) ==> muduo ==> Callee（中间那一块都是框架做的事情）
     * 2. Callee ==> Login(LoginRequest) ==> 交到下面重写的 Login 方法
    */
    void Login(::google::protobuf::RpcController *controller,
               const ::fixbug::LoginRequest *request,  // 请求
               ::fixbug::LoginResponse *response,  // 处理业务后的响应
               ::google::protobuf::Closure *done)  // 执行回调
    {
        // 框架给业务上报了请求参数 LoginRequest，业务获取相应数据做本地业务（框架已经反序列化完了）
        std::string name = request->name();
        std::string pwd = request->pwd();

        // Callee 这边做本地业务
        bool login_result = Login(name, pwd);

        // 把响应写入  错误码 错误消息 返回值
        fixbug::ResultCode *code = response->mutable_result();
        code->set_errcode(0);
        code->set_errmsg("");
        response->set_success(login_result);

        // 执行回调操作 Closure是个抽象类，要继承重写虚函数
        // 执行响应对象数据的序列号和网络发送（框架完成）
        done->Run();
    }

    void Register(::google::protobuf::RpcController* controller,
                  const ::fixbug::RegisterRequest* request,
                  ::fixbug::RegisterResponse* response,
                  ::google::protobuf::Closure* done)
    {
        // 参数解析
        uint32_t id = request->id();
        std::string name = request->name();
        std::string pwd = request->pwd();

        // 本地业务
        bool register_result = Register(id, name, pwd);

        // 填写响应 response 内容
        response->mutable_result()->set_errcode(0);
        response->mutable_result()->set_errmsg("");
        response->set_success(register_result);

        done->Run();  // 把 response 序列化发送到网络上
    }
};

int main(int argc, char **argv)
{
    // 本地的时候
    // UserService service;
    // service.Login("", "");

    // 调用框架的初始化操作 provider -i config.conf
    MprpcApplication::Init(argc, argv);

    // provider 是一个 rpc 网络服务对象，把 UserService 对象发布到 rpc 节点上
    RpcProvider provider;
    provider.NotifyService(new UserService);

    // 启动一个 rpc 发布节点，Run以后，进程进入阻塞状态，等待远程的 rpc 调用请求
    provider.Run();

    return 0;
}